home *** CD-ROM | disk | FTP | other *** search
- { Copyright 1993 by Michael W. Armstrong.
- 2800 Skipwith Rd
- Richmond, VA 23294
-
- Compuserve ID 72740, 1145
- This program is entered as Shareware. If you find it useful, a small
- donation would be appreciated. Feel free to incorporate the code into
- your own programs.
- }
-
- { NOTE : The CD_Vars and CDUNIT_P are at the end of this code }
-
-
- {$X+}
- program CDPlay;
-
- {$IfDef Windows}
- {$C PRELOAD}
- uses CD_Vars, CDUnit_P, WinCRT, WinProcs;
- {$Else}
- uses CD_Vars, CDUnit_P, CRT, Drivers;
- {$EndIf}
-
- Type
- TotPlayRec = Record
- Frames,
- Seconds,
- Minutes,
- Nada : Byte;
- End;
-
- Var
- GoodDisk : Boolean;
- SaveExit : Pointer;
- OldMode : Word;
- CurrentTrack,
- StartTrack,
- EndTrack : Integer;
- TotPlay : TotPlayRec;
- TrackInfo : Array[1..99] of PAudioTrackInfo;
-
- function LeadingZero(w: Word): String;
- var s: String;
- begin
- Str(w:0, s);
- LeadingZero := Copy('00', 1, 2 - Length(s)) + s;
- end;
-
-
- procedure DrawScreen;
- Const TStr = '%03d:%02d';
- VStr = '%1d.%2d';
- Var FStr : PChar;
- NStr : String;
- Param: Array[1..2] of LongInt;
- Code : Integer;
- begin
- WriteLn('CD ROM Audio Disk Player');
- WriteLn('Copyright 1992 by M. W. ARMSTRONG');
- Param[1] := MSCDEX_Version.Major;
- Param[2] := MSCDEX_Version.Minor;
-
- {$IfDef Windows}
- wvsPrintf(FStr, VStr, Param);
- {$Else}
- FormatStr(NStr, VStr, Param);
- {$EndIf}
-
- WriteLn('MSCDEX Version ', NStr);
- Str(NumberOfCD, NStr);
- WriteLn('Number of CD ROM Drives is: '+Nstr);
- WriteLn('First CD Drive Letter is : '+Chr(FirstCD+65));
- WriteLn('There are ' + LeadingZero(EndTrack - StartTrack + 1) + ' Tracks on this disk');
- Code := 1;
- end;
- {***********************************************************************}
-
- {***********************************************************************}
-
-
- procedure Setup;
- Var
- LeadOut,
- StartP,
- TotalPlayTime : LongInt;
- I : Integer;
- A,B,C : LongInt;
- Track : Byte;
- EA : Array[1..4] of Byte;
- SP,EP : LongInt;
-
- Begin
- FillChar(AudioDiskInfo, SizeOf(AudioDiskInfo), #0);
- DeviceStatus;
- If Audio THEN
- Begin
- Audio_Disk_Info;
- TotalPlayTime := 0;
- LeadOut := AudioDiskInfo.LeadOutTrack;
-
- StartTrack := AudioDiskInfo.LowestTrack;
- EndTrack := AudioDiskInfo.HighestTrack;
- CurrentTrack := StartTrack;
- I := StartTrack-1;
-
- Repeat { Checks if Audio Track or Data Track }
- Inc(I);
- Track := I;
- Audio_Track_Info(StartP, Track);
- Until (Track AND 64 = 0) OR (I = EndTrack);
-
- StartTrack := I;
-
- For I := StartTrack to EndTrack DO
- Begin
- Track := I;
- Audio_Track_Info(StartP, Track);
- New(TrackInfo[I]);
- FillChar(TrackInfo[I]^, SizeOf(TrackInfo[I]^), #0);
- TrackInfo[I]^.Track := I;
- TrackInfo[I]^.StartPoint := StartP;
- TrackInfo[I]^.TrackControl := Track;
- End;
-
- For I := StartTrack to EndTrack - 1 DO
- TrackInfo[I]^.EndPoint := TrackInfo[I+1]^.StartPoint;
- TrackInfo[EndTrack]^.EndPoint := LeadOut;
-
- For I := StartTrack to EndTrack DO
- Move(TrackInfo[I]^.EndPoint, TrackInfo[I]^.Frames, 4);
-
- TrackInfo[StartTrack]^.PlayMin := TrackInfo[StartTrack]^.Minutes;
- TrackInfo[StartTrack]^.PlaySec := TrackInfo[StartTrack]^.Seconds - 2;
-
- For I := StartTrack + 1 to EndTrack DO
- Begin
- EP := (TrackInfo[I]^.Minutes * 60) + TrackInfo[I]^.Seconds;
- SP := (TrackInfo[I-1]^.Minutes * 60) + TrackInfo[I-1]^.Seconds;
- EP := EP - SP;
- TrackInfo[I]^.PlayMin := EP DIV 60;
- TrackInfo[I]^.PlaySec := EP Mod 60;
- End;
-
- TotalPlayTime := AudioDiskInfo.LeadOutTrack - TrackInfo[StartTrack]^.StartPoint;
- Move(TotalPlayTime, TotPlay, 4);
- End;
- end;
-
- {***********************************************************************}
-
-
- Begin
- Setup;
- If Audio THEN
- If Playing THEN
- StopAudio
- ELSE
- Begin
- StopAudio;
- Play_Audio(TrackInfo[StartTrack]^.StartPoint,
- TrackInfo[EndTrack]^.EndPoint);
- Audio_Status_Info;
- DrawScreen;
- End
- ELSE
- WriteLn('This is not an Audio CD');
- WriteLn('UPC Code is: ', UPC_Code);
- end.
-
- { ----------------------------------- CUT HERE -------------------- }
-
- Unit CD_Vars;
-
- Interface
-
- Type
- ListBuf = Record
- UnitCode : Byte;
- UnitSeg,
- UnitOfs : Word;
- end;
- VTOCArray = Array[1..2048] of Byte;
- DriveByteArray = Array[1..128] of Byte;
-
- Req_Hdr = Record
- Len : Byte;
- SubUnit : Byte;
- Command : Byte;
- Status : Word;
- Reserved: Array[1..8] of Byte;
- End;
-
- Const
- Init = 0;
- IoCtlInput = 3;
- InputFlush = 7;
- IOCtlOutput= 12;
- DevOpen = 13;
- DevClose = 14;
- ReadLong = 128;
- ReadLongP = 130;
- SeekCmd = 131;
- PlayCD = 132;
- StopPlay = 133;
- ResumePlay = 136;
-
- Type
-
- Audio_Play = Record
- APReq : Req_Hdr;
- AddrMode : Byte;
- Start : LongInt;
- NumSecs : LongInt;
- end;
-
- IOControlBlock = Record
- IOReq_Hdr : Req_Hdr;
- MediaDesc : Byte;
- TransAddr : Pointer;
- NumBytes : Word;
- StartSec : Word;
- ReqVol : Pointer;
- TransBlock: Array[1..130] OF Byte;
- End;
-
- ReadControl = Record
- IOReq_Hdr : Req_Hdr;
- AddrMode : Byte;
- TransAddr : Pointer;
- NumSecs : Word;
- StartSec : LongInt;
- ReadMode : Byte;
- IL_Size,
- IL_Skip : Byte;
- End;
-
- AudioDiskInfoRec = Record
- LowestTrack : Byte;
- HighestTrack : Byte;
- LeadOutTrack : LongInt;
- End;
-
- PAudioTrackInfo = ^AudioTrackInfoRec;
- AudioTrackInfoRec = Record
- Track : Integer;
- StartPoint : LongInt;
- EndPoint : LongInt;
- Frames,
- Seconds,
- Minutes,
- PlayMin,
- PlaySec,
- TrackControl : Byte;
- end;
-
- MSCDEX_Ver_Rec = Record
- Major,
- Minor : Integer;
- End;
-
- DirBufRec = Record
- XAR_Len : Byte;
- FileStart : LongInt;
- BlockSize : Integer;
- FileLen : LongInt;
- DT : Byte;
- Flags : Byte;
- InterSize : Byte;
- InterSkip : Byte;
- VSSN : Integer;
- NameLen : Byte;
- NameArray : Array[1..38] of Char;
- FileVer : Integer;
- SysUseLen : Byte;
- SysUseData: Array[1..220] of Byte;
- FileName : String[38];
- end;
-
- Q_Channel_Rec = Record
- Control : Byte;
- Track : Byte;
- Index : Byte;
- Minutes : Byte;
- Seconds : Byte;
- Frame : Byte;
- Zero : Byte;
- AMinutes : Byte;
- ASeconds : Byte;
- AFrame : Byte;
- End;
-
- Var
- AudioChannel : Array[1..9] of Byte;
- RedBook,
- Audio,
- DoorOpen,
- DoorLocked,
- AudioManip,
- DiscInDrive : Boolean;
- AudioDiskInfo : AudioDiskInfoRec;
- DriverList : Array[1..26] of ListBuf;
- NumberOfCD : Integer;
- FirstCD : Integer;
- UnitList : Array[1..26] of Byte;
- MSCDEX_Version : MSCDEX_Ver_Rec;
- QChannelInfo : Q_Channel_Rec;
- Busy,
- Playing,
- Paused : Boolean;
- Last_Start,
- Last_End : LongInt;
- DirBuf : DirBufRec;
-
- Implementation
-
- Begin
- FillChar(DriverList, SizeOf(DriverList), #0);
- FillChar(UnitList, SizeOf(UnitList), #0);
- NumberOfCD := 0;
- FirstCD := 0;
- MSCDEX_Version.Major := 0;
- MSCDEX_Version.Minor := 0;
- end.
-
- { ----------------------------------- CUT HERE -------------------- }
-
- {$X+}
-
- Unit CDUnit_P;
-
- Interface
-
- {Include the appropriate units.}
-
- {$IfDef Windows}
- {$C PRELOAD}
- Uses Strings, WinCRT, WinDOS, WinProcs, SimRMI, CD_Vars;
- {$EndIf}
- {$IfDef DPMI}
- Uses Strings, CRT, DOS, WinAPI, SimRMI, CD_Vars;
- {$EndIf}
- {$IfDef MSDOS}
- Uses Strings, CRT, DOS, CD_Vars;
- {$EndIf}
-
- Var
- Drive : Integer; { Must set drive before all operations }
- SubUnit : Integer;
-
- function File_Name(var Code : Integer) : String;
-
- function Read_VTOC(var VTOC : VTOCArray;
- var Index : Integer) : Boolean;
-
- procedure CD_Check(var Code : Integer);
-
- procedure Vol_Desc(Var Code : Integer;
- var ErrCode : Integer);
-
- procedure Get_Dir_Entry(PathName : String;
- var Format, ErrCode : Integer);
-
- procedure DeviceStatus;
-
- procedure Audio_Channel_Info;
-
- procedure Audio_Disk_Info;
-
- procedure Audio_Track_Info(Var StartPoint : LongInt;
- Var TrackControl : Byte);
-
- procedure Audio_Status_Info;
-
- procedure Q_Channel_Info;
-
- procedure Lock(LockDrive : Boolean);
-
- procedure Reset;
-
- procedure Eject;
-
- procedure CloseTray;
-
- procedure Resume_Play;
-
- procedure Pause_Audio;
-
- procedure Play_Audio(StartSec, EndSec : LongInt);
-
- function StopAudio : Boolean;
-
- function Sector_Size(ReadMode : Byte) : Word;
-
- function Volume_Size : LongInt;
-
- function Media_Changed : Boolean;
-
- function Head_Location(AddrMode : Byte) : LongInt;
-
- procedure Read_Drive_Bytes(Var ReadBytes : DriveByteArray);
-
- function UPC_Code : String;
-
- Implementation
-
- Const
- CarryFlag = $0001;
-
- Var
- {$IfDef MSDOS}
- Regs : Registers;
- {$Else}
- Regs :TRealModeRecord; { from SimRMI Unit }
- {$EndIf}
- DOSOffset,
- DOSSegment,
- DOSSelector:Word;
- AllocateLong:Longint;
- IOBlock : Pointer;
-
-
- {$IfDef MSDOS}
- { standard DOS routines for segments and pointers }
- function GetIOBlock(var Block : Pointer; Size : Word) : Boolean;
- begin
- GetMem(Block, Size);
- DOSSegment := Seg(Block^);
- DOSOffset := Ofs(Block^);
- GetIOBlock := TRUE;
- end;
-
- function FreeIOBlock(var Block: Pointer) : Boolean;
- begin
- FreeMem(Block, SizeOf(Block^));
- DOSSegment := 0;
- DOSSelector := 0;
- DOSOffset := 0;
- FreeIOBlock := TRUE;
- end;
-
- {$ELSE}
-
- { Get a block in DOS and set pointer values. DOSSelector is used
- to access the block under protected mode. DOSSegment accesses the
- block in real mode }
-
- function GetIOBlock(var Block : Pointer; Size : Word) : Boolean;
- begin
- AllocateLong:=GlobalDOSAlloc(Size); { enough extra room for string }
- If AllocateLong<>0 Then {If allocation was successful...}
- Begin
- DOSSegment:=AllocateLong SHR 16; {Get the real mode segment of the memory}
- DOSSelector:=AllocateLong AND $FFFF; {Get the protected mode selector of the memory}
- DOSOffset := 0;
- Block := Ptr(DOSSelector, 0);
- GetIOBlock := TRUE;
- End
- ELSE
- GetIOBlock := FALSE;
- end;
-
- { Free the DOS block and dereference the pointer }
-
- function FreeIOBlock(var Block: Pointer) : Boolean;
- begin
- DOSSelector := GlobalDOSFree(DOSSelector);
- DOSSegment := 0;
- Block := NIL;
- FreeIOBlock := (DOSSelector = 0);
- end;
-
- {$EndIf}
-
- procedure Clear_Regs;
- begin
- FillChar(Regs, SizeOf(Regs), #0);
- end;
-
- procedure CD_Intr;
- begin
- Regs.AH := $15;
-
- {$IfDef MSDOS}
- Intr($2F, Regs); { Call DOS normally }
- {$Else}
- If NOT SimRealModeInt($2F,@Regs) Then {Call DOS through the DPMI}
- Halt(100);
- {$EndIf}
- end;
-
- procedure MSCDEX_Ver;
- begin
- Clear_Regs;
- Regs.AL := $0C;
- Regs.BX := $0000;
- CD_Intr;
- MSCDEX_Version.Minor := 0;
- If Regs.BX = 0 Then
- MSCDEX_Version.Major := 1
- ELSE
- Begin
- MSCDEX_Version.Major := Regs.BH;
- MSCDEX_Version.Minor := Regs.BL;
- End;
- end;
-
- procedure Initialize;
- begin
- NumberOfCD := 0;
- Clear_Regs;
- Regs.AL := $00;
- Regs.BX := $0000;
- CD_Intr;
- If Regs.BX <> 0 THEN
- Begin
- NumberOfCD := Regs.BX;
- FirstCD := Regs.CX;
- Clear_Regs;
- FillChar(DriverList, SizeOf(DriverList), #0);
- FillChar(UnitList, SizeOf(UnitList), #0);
- Regs.AL := $01; { Get List of Driver Header Addresses }
- Regs.ES := Seg(DriverList);
- Regs.BX := Ofs(DriverList);
- CD_Intr;
- Clear_Regs;
- Regs.AL := $0D; { Get List of CD-ROM Units }
- Regs.ES := Seg(UnitList);
- Regs.BX := Ofs(UnitList);
- CD_Intr;
- MSCDEX_Ver;
- End;
- end;
-
-
- function File_Name(var Code : Integer) : String;
- Var
- FN : Pointer;
- begin
- Clear_Regs;
- If NOT GetIOBlock(FN, 64) THEN
- Exit;
- FillChar(FN, SizeOf(FN), #0);
- Regs.AL := Code + 1;
- {
- Copyright Filename = 1
- Abstract Filename = 2
- Bibliographic Filename = 3
- }
- Regs.CX := Drive;
- Regs.ES := DOSSegment;
- Regs.BX := DOSOffset;
- CD_Intr;
- Code := Regs.AX;
- If (Regs.Flags AND CarryFlag) = 0 THEN
- File_Name := StrPas(FN)
- ELSE
- File_Name := '';
- FreeIOBlock(FN);
- end;
-
-
- function Read_VTOC(var VTOC : VTOCArray;
- var Index : Integer) : Boolean;
- { On entry -
- Index = Vol Desc Number to read from 0 to ?
- On return
- Case Index of
- 1 : Standard Volume Descriptor
- $FF : Volume Descriptor Terminator
- 0 : All others
- }
- var
- PVTOC : Pointer;
-
- begin
- Clear_Regs;
- If NOT GetIOBlock(PVTOC, SizeOf(VTOCArray)) THEN
- Exit;
- FillChar(PVTOC^, SizeOf(PVTOC^), #0);
- Regs.AL := $05;
- Regs.CX := Drive;
- Regs.DX := Index;
- Regs.ES := DOSSegment;
- Regs.BX := DOSOffset;
- CD_Intr;
- Index := Regs.AX;
- Move(PVTOC^,VTOC, SizeOf(VTOC));
- If (Regs.Flags AND CarryFlag) = 0 THEN
- Read_VTOC := TRUE
- ELSE
- Read_VTOC := FALSE;
- FreeIOBlock(PVTOC);
- end;
-
- procedure CD_Check(var Code : Integer);
- begin
- Clear_Regs;
- Regs.AL := $0B;
- Regs.BX := $0000;
- Regs.CX := Drive;
- CD_Intr;
- If Regs.BX <> $ADAD THEN
- Code := 2
- ELSE
- Begin
- If Regs.AX <> 0 THEN
- Code := 0
- ELSE
- Code := 1;
- End;
- end;
-
-
- procedure Vol_Desc(Var Code : Integer;
- var ErrCode : Integer);
-
- function Get_Vol_Desc : Byte;
- begin
- Clear_Regs;
- Regs.CX := Drive;
- Regs.AL := $0E;
- Regs.BX := $0000;
- CD_Intr;
- Code := Regs.AX;
- If (Regs.Flags AND CarryFlag) <> 0 THEN
- ErrCode := $FF;
- Get_Vol_Desc := Regs.DH;
- end;
-
- begin
- Clear_Regs;
- ErrCode := 0;
- If Code <> 0 THEN
- Begin
- Regs.DH := Code;
- Regs.DL := 0;
- Regs.BX := $0001;
- Regs.AL := $0E;
- Regs.CX := Drive;
- CD_Intr;
- Code := Regs.AX;
- If (Regs.Flags AND CarryFlag) <> 0 THEN
- ErrCode := $FF;
- End;
- If ErrCode = 0 THEN
- Code := Get_Vol_Desc;
- end;
-
- procedure Get_Dir_Entry(PathName : String;
- var Format, ErrCode : Integer);
- var
- PN : PChar;
- DB : Pointer;
- begin
- FillChar(DirBuf, SizeOf(DirBuf), #0);
- PathName := PathName + #0;
- If NOT GetIOBlock(DB, SizeOf(DirBufRec) + 256) THEN
- Exit;
- PN := Ptr(DOSSelector, SizeOf(DirBufRec) + 1);
- Clear_Regs;
- Regs.AL := $0F;
- Regs.CL := Drive;
- Regs.CH := 1;
- Regs.ES := DOSSegment;
- Regs.BX := SizeOf(DirBufRec) + 1;
- Regs.SI := DOSSegment;
- Regs.DI := DOSOffset;
- CD_Intr;
- ErrCode := Regs.AX;
- If (Regs.Flags AND CarryFlag) = 0 THEN
- Begin
- Move(DB^, DirBuf, SizeOf(DirBuf));
- Move(DirBuf.NameArray[1], DirBuf.FileName[1], 38);
- DirBuf.FileName[0] := #12; { File names are only 8.3 }
- Format := Regs.AX
- End
- ELSE
- Format := $FF;
- FreeIOBlock(DB);
- end;
-
- function IO_Control(Command, NumberOfBytes, TransferBytes,
- ReturnBytes, StartPoint : Byte;
- var Bytes, TransferBlock): Byte;
- var
- I : Word;
- begin
- If NOT GetIOBlock(IOBlock, SizeOf(IOControlBlock)) THEN
- Exit;
- With IOControlBlock(IOBlock^) DO
- Begin
- I := Ofs(TransBlock[1]) - Ofs(IOReq_Hdr);
- NumBytes := NumberOfBytes;
- IOReq_Hdr.Len := 26;
- IOReq_Hdr.SubUnit := SubUnit;
- IOReq_Hdr.Status := 0;
- TransAddr := Ptr(DOSSegment, I); { 23 bytes into the IOBlock^ }
- IOReq_Hdr.Command := Command;
- Move(Bytes, TransBlock[1], TransferBytes);
- Clear_Regs;
- Regs.AL := $10;
- Regs.CX := Drive;
- Regs.ES := DOSSegment;
- Regs.BX := DOSOffset;
- CD_Intr;
- Busy := (IOReq_Hdr.Status AND 512) <> 0;
- If ((IOReq_Hdr.Status AND 32768) <> 0) THEN
- I := IOReq_Hdr.Status AND $FF
- ELSE
- I := 0;
- If ReturnBytes <> 0 THEN
- Move(TransBlock[StartPoint], TransferBlock, ReturnBytes);
- End;
- IO_Control := I;
- FreeIOBlock(IOBlock);
- end;
-
- procedure Audio_Channel_Info;
- var
- Bytes : Byte;
- begin
- Bytes := 4;
- IO_Control(IOCtlInput, 9, 1, 9, 1, Bytes, AudioChannel);
- End;
-
- procedure DeviceStatus;
- var
- Bytes : Array[1..2] OF Byte;
- Status: Word;
- begin
- Bytes[1] := 6;
-
- IO_Control(IOCtlInput, 5, 1, 2, 2, Bytes, Bytes);
- Move(Bytes, Status, 2);
-
- DoorOpen := Status AND 1 <> 0;
- DoorLocked := Status AND 2 = 0;
- Audio := Status AND 16 <> 0;
- AudioManip := Status AND 256 <> 0;
- DiscInDrive := Status AND 2048 = 0;
- RedBook := Status AND 1024 <> 0;
- End;
-
- procedure Audio_Disk_Info;
- var Bytes : Byte;
- begin
- Bytes := 10;
- IO_Control(IOCtlInput, 7, 1, 6, 2, Bytes, AudioDiskInfo);
- Playing := Busy;
- end;
-
- procedure Audio_Track_Info(Var StartPoint : LongInt;
- Var TrackControl : Byte);
- var
- Bytes : Array[1..5] Of BYTE;
- begin
- Bytes[1] := 11;
- Bytes[2] := TrackControl; { Track number }
-
- IO_Control(IOCtlInput, 7, 2, 5, 3, Bytes, Bytes);
- Move(Bytes[1], StartPoint, 4);
- TrackControl := Bytes[5];
-
- Playing := Busy;
- end;
-
- procedure Q_Channel_Info;
- var
- Bytes : Byte;
- begin
- Bytes := 12;
- IO_Control(IOCtlInput, 11, 1, 11, 2, Bytes, QChannelInfo);
- end;
-
- procedure Audio_Status_Info;
- var
- Bytes : Array[1..11] Of Byte;
- begin
- Bytes[1] := 15;
- IO_Control(IOCtlInput, 11, 1, 8, 2, Bytes, Bytes);
- Paused := (Word(Bytes[2]) AND 1) <> 0;
- Move(Bytes[4], Last_Start, 4);
- Move(Bytes[8], Last_End, 4);
- Playing := Busy;
- end;
-
- procedure Eject;
- var
- Bytes : Byte;
- begin
- Bytes := 0;
- IO_Control(IOCtlOutput, 1, 1, 0, 0, Bytes, Bytes);
- end;
-
- procedure Reset;
- var Bytes : Byte;
- begin
- Bytes := 2;
- IO_Control(IOCtlOutput, 1, 1, 0, 0, Bytes, Bytes);
- Busy := TRUE;
- end;
-
- procedure Lock(LockDrive : Boolean);
- var
- Bytes : Array[1..2] Of Byte;
- begin
- Bytes[1] := 1;
- If LockDrive THEN
- Bytes[2] := 1
- ELSE
- Bytes[2] := 0;
- IO_Control(IOCtlOutput, 2, 2, 0, 0, Bytes, Bytes);
- end;
-
- procedure CloseTray;
- var Bytes : Byte;
- begin
- Bytes := 5;
- IO_Control(IOCtlOutput, 1, 1, 0, 0, Bytes, Bytes);
- end;
-
- Var
- AudioPlay : Pointer;
-
-
- function Play(StartLoc, NumSec : LongInt) : Boolean;
- begin
-
- If NOT GetIOBlock(AudioPlay, SizeOf(Audio_Play)) THEN
- Exit;
- With Audio_Play(AudioPlay^) DO
- Begin
- APReq.Command := PlayCD;
- APReq.Len := 22;
- APReq.SubUnit := SubUnit;
- Start := StartLoc;
- NumSecs := NumSec;
- AddrMode := 1;
- Regs.AL := $10;
- Regs.CX := Drive;
- Regs.ES := DOSSegment;
- Regs.BX := DOSOffset;
- CD_Intr;
- Play := ((APReq.Status AND 32768) = 0);
- End;
- FreeIOBlock(AudioPlay);
- end;
-
- procedure Play_Audio(StartSec, EndSec : LongInt);
- Var
- SP,
- EP : LongInt;
- SArray : Array[1..4] Of Byte;
- EArray : Array[1..4] Of Byte;
- begin
- Move(StartSec, SArray[1], 4);
- Move(EndSec, EArray[1], 4);
- SP := SArray[3]; { Must use longint or get negative result }
- SP := (SP*75*60) + (SArray[2]*75) + SArray[1];
- EP := EArray[3];
- EP := (EP*75*60) + (EArray[2]*75) + EArray[1];
- EP := EP-SP;
-
- Playing := Play(StartSec, EP);
- Audio_Status_Info;
- end;
-
- procedure Pause_Audio;
- begin
-
- If Playing THEN
- Begin
- If NOT GetIOBlock(AudioPlay, SizeOf(Audio_Play)) THEN
- Exit;
- With Audio_Play(AudioPlay^) DO
- Begin
- APReq.Command := StopPlay;
- APReq.Len := 13;
- APReq.SubUnit := SubUnit;
- End;
- Regs.AL := $10;
- Regs.CX := Drive;
- Regs.ES := DOSSegment;
- Regs.BX := DOSOffset;
- CD_Intr;
- FreeIOBlock(AudioPlay);
- end;
- Audio_Status_Info;
- Playing := FALSE;
- end;
-
- procedure Resume_Play;
- begin
- If NOT GetIOBlock(AudioPlay, SizeOf(Audio_Play)) THEN
- Exit;
- With Audio_Play(AudioPlay^) DO
- Begin
- APReq.Command := ResumePlay;
- APReq.Len := 13;
- APReq.SubUnit := SubUnit;
- End;
- Regs.AL := $10;
- Regs.CX := Drive;
- Regs.ES := DOSSegment;
- Regs.BX := DOSOffset;
- CD_Intr;
- Audio_Status_Info;
- FreeIOBlock(AudioPlay); { free DOS block anbd dereference pointer }
- end;
-
- function StopAudio : Boolean;
- begin
-
- If NOT GetIOBlock(AudioPlay, SizeOf(Audio_Play)) THEN
- Exit;
- With Audio_Play(AudioPlay^) DO
- Begin
- APReq.Command := StopPlay;
- APReq.Len := 13;
- APReq.SubUnit := SubUnit;
- Regs.AL := $10;
- Regs.CX := Drive;
- Regs.ES := DOSSegment;
- Regs.BX := DOSOffset;
- CD_Intr;
- StopAudio := ((APReq.Status AND 32768) = 0);
- End;
- FreeIOBlock(AudioPlay);
- end;
-
- function Sector_Size(ReadMode : Byte) : Word;
- Var
- SecSize : Word;
- Bytes : Array[1..2] Of Byte;
- begin
- Bytes[1] := 7;
- Bytes[2] := ReadMode;
- IO_Control(IOCtlInput, 4, 2, 2, 3, Bytes, SecSize);
- Sector_Size := SecSize;
- End;
-
- function Volume_Size : LongInt;
- Var
- VolSize : LongInt;
- Bytes : Byte;
- begin
- Bytes := 8;
- IO_Control(IOCtlInput, 5, 1, 4, 2, Bytes, VolSize);
- Volume_Size := VolSize;
- End;
-
- function Media_Changed : Boolean;
-
- { 1 : Media not changed
- 0 : Don't Know
- -1 : Media changed
- }
- var
- MedChng : Byte;
- Bytes : Byte;
- begin
- Bytes := 9;
- IO_Control(IOCtlInput, 2, 1, 4, 2, Bytes, MedChng);
- Inc(MedChng);
- If MedChng IN [1,0] THEN
- Media_Changed := True
- ELSE
- Media_Changed := False;
- End;
-
- function Head_Location(AddrMode : Byte) : LongInt;
- Var
- HeadLoc : Longint;
- Bytes : Array[1..2] Of Byte;
- begin
- Bytes[1] := 1;
- Bytes[2] := AddrMode;
- IO_Control(IOCtlInput, 6, 2, 4, 3, Bytes, HeadLoc);
- Head_Location := HeadLoc;
- End;
-
- procedure Read_Drive_Bytes(Var ReadBytes : DriveByteArray);
- var
- Bytes : Byte;
- Begin
- Bytes := 5;
- IO_Control(IOCtlInput, 130, 1, 128, 3, Bytes, ReadBytes);
- End;
-
- function UPC_Code : String;
- Var
- I, J, K : Integer;
- TempStr : String;
- Bytes : Array[1..11] Of Byte;
- Begin
- TempStr := '';
- FillChar(Bytes, SizeOf(Bytes), #0);
- Bytes[1] := 14;
- If (IO_Control(IOCtlInput, 11, 1, 11, 1, Bytes, Bytes) <> 0) THEN
- TempStr := 'No UPC Code'
- ELSE
- Begin
- For I := 3 to 9 DO
- Begin
- J := (Bytes[I] AND $F0) SHR 4;
- K := Bytes[I] AND $0F;
- TempStr := TempStr + Chr(J + 48);
- TempStr := TempStr + Chr(K + 48);
- End;
- If Length(TempStr) > 13 THEN
- TempStr := Copy(TempSTr, 1, 13);
- End;
- UPC_Code := TempStr;
- End;
-
- {************************************************************}
- {$IfDef MSDOS}
- {$ELSE}
- {$F+}
- var
- ExitRoutine : Pointer;
- procedure MyExit;
- begin
- ExitProc := ExitRoutine;
- If DOSSelector <> 0 THEN
- Begin
- GlobalDOSFree(DOSSelector);
- WriteLn('DOS Selector not free');
- End
- ELSE
- WriteLn('DOS Selector free');
- end;
- {$EndIf}
-
- Begin
- NumberOfCD := 0;
- FirstCD := 0;
- FillChar(MSCDEX_Version, SizeOf(MSCDEX_Version), #0);
- Initialize;
- Drive := FirstCD;
- SubUnit := 0;
- {$IfDef MSDOS}
- {$ELSE}
- ExitRoutine := ExitProc;
- ExitProc := @MyExit;
- {$EndIf}
- End.